package com.strong.config.security.handler;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.strong.utils.mvc.pojo.view.ReplyVO;
import com.strong.utils.security.SecurityUtils;
import com.strong.utils.security.jwt.JwtTokenUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

import static com.strong.utils.security.SecurityUtils.*;

/**
 * jwt注销成功处理程序
 *
 * @author simen
 * @date 2022/02/15
 */
@Slf4j
@Component("JwtLogoutSuccessHandler")
public class JwtLogoutSuccessHandler implements LogoutSuccessHandler {

    public static final String LOGOUT_SUCCESS = "登出成功";

    /**
     * jwt token 工具类
     */
    private final JwtTokenUtils jwtTokenUtils;

    /**
     * 实例化
     *
     * @param jwtTokenUtils jwt token 工具类
     */
    public JwtLogoutSuccessHandler(JwtTokenUtils jwtTokenUtils) {
        this.jwtTokenUtils = jwtTokenUtils;
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
        // 从Request中取出授权字符串
        final String strAuthorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        // 判断授权字符串是否以STR_AUTHENTICATION_PREFIX开头
        if (StrUtil.startWith(strAuthorization, STR_AUTHENTICATION_PREFIX)) {
            // 获取认证的JWT token
            String strJwtToken = strAuthorization.replace(STR_AUTHENTICATION_PREFIX, "");
            // 判断token是否为空
            if (StrUtil.isNotBlank(strJwtToken)) {
                // 验证凭证，失败则抛出错误
                try {
                    jwtTokenUtils.verifyToken(strJwtToken);
                    // 从token中获取用户名
                    String strUserName = jwtTokenUtils.getAudience(strJwtToken);
                    // 断言用户名非空
                    Assert.notBlank(strUserName, "当前用户不存在");

                    // 删除系统缓存的用户JWT Token
                    MAP_SYSTEM_USER_TOKEN.remove(strUserName);
                    // 删除系统缓存的用户身份验证对象
                    MAP_SYSTEM_USER_AUTHENTICATION.remove(strUserName);

                    log.info("[{}]登出成功，已清除该用户登录缓存信息", strUserName);
                } catch (Exception ignored) {
                    log.info("登出失败");
                }
            }
        }
        // 返回登出成功信息
        SecurityUtils.returnReplyJsonResponse(response, HttpServletResponse.SC_OK, new ReplyVO<>(LOGOUT_SUCCESS));
    }
}
